package cn.com.doone.common.uc.infrastructure.ldap;

import java.sql.Timestamp;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

import javax.naming.NamingEnumeration;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.LdapContext;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.shiro.realm.ldap.LdapUtils;
import org.springframework.stereotype.Repository;

import cn.com.doone.common.uc.domain.rs.IRegisterLdapRepository;
import cn.com.doone.common.uc.infrastructure.jdbc.AbstractLdapRepository;
import cn.com.doone.common.uc.service.dto.UserGroup;
import cn.com.doone.common.uc.service.dto.UserInfo;
import cn.com.doone.common.uc.utils.PasswordUtils;

@Repository("registerLdapRepository")
public class RegisterLdapRepository extends AbstractLdapRepository implements IRegisterLdapRepository {
	

	@Override
	public String addTenant(UserGroup userGroup) throws Exception {
		String distinguishedName = "";
		LdapContext ldapContext = null;
		try {
			
			String ouName = userGroup.getGroupName();
			String groupCode = userGroup.getGroupCode();
			String tenantCode = userGroup.getTenantCode();
			
			if (groupCode == null) {
				groupCode = "TEMP_CODE";
			}
			
			ldapContext = ldapContextFactory.getSystemLdapContext(); 
			distinguishedName = "OU=" + ouName + ",DC=doone,DC=com,DC=cn";
            Attributes newAttributes = new BasicAttributes(true);
            Attribute oc = new BasicAttribute("objectClass");
            oc.add("top");
            oc.add("xdwOrganization");
            newAttributes.put(oc);
            newAttributes.put(new BasicAttribute("ou", ouName));
            newAttributes.put(new BasicAttribute("groupCode", groupCode));
            newAttributes.put(new BasicAttribute("groupName", ouName));
            newAttributes.put(new BasicAttribute("groupType", "1"));
            newAttributes.put(new BasicAttribute("tenantCode", tenantCode));
            newAttributes.put(new BasicAttribute("status", "1"));
            ldapContext.createSubcontext(distinguishedName, newAttributes);
		} catch (Exception e) {
			throw e;
		} finally {
            LdapUtils.closeContext(ldapContext);
        }
		
		return distinguishedName;
		
	}
	
	/**
	 * 更新租户
	 */
	public void updateTenant(UserGroup userGroup) throws Exception {
		String distinguishedName = "";
		LdapContext ldapContext = null;
		try {
			ldapContext = ldapContextFactory.getSystemLdapContext(); 
			String ouName = userGroup.getGroupName();
			String groupCode = userGroup.getGroupCode();
			String tenantCode = userGroup.getTenantCode();
			
			distinguishedName = "OU=" + ouName + ",DC=doone,DC=com,DC=cn";
			
			ModificationItem[] mods = new ModificationItem[1];   
			// 替换
	        mods[0] = new ModificationItem(LdapContext.REPLACE_ATTRIBUTE, new BasicAttribute("groupCode", groupCode));   
	        mods[1] = new ModificationItem(LdapContext.REPLACE_ATTRIBUTE, new BasicAttribute("tenantCode", tenantCode));   
	        // mods[2] = new ModificationItem(LdapContext.REPLACE_ATTRIBUTE, new BasicAttribute("groupName", ouName));   
		 
	        ldapContext.modifyAttributes(distinguishedName, mods);
		} catch (Exception e) {
			throw e;
		} finally {
            LdapUtils.closeContext(ldapContext);
        }
		
	}

	@Override
	public void addUser(String tenantFullName, String tenantCode, UserInfo userInfo) throws Exception {
		LdapContext ldapContext = null;
		try {
			ldapContext = ldapContextFactory.getSystemLdapContext();
			int userInfoId = userInfo.getUserInfoId();
			String newUsername = userInfo.getUserAccount();
			String newPassword = userInfo.getPassword();
			String nickname = userInfo.getNickname();
			String realname = userInfo.getRealname();
			
			String distinguishedName = "CN=" + newUsername + "," + tenantFullName;
            Attributes newAttributes = new BasicAttributes(true);
            Attribute oc = new BasicAttribute("objectclass");

            oc.add("top");   
            oc.add("account");
            oc.add("xdwAccount");
            newAttributes.put(oc);   
            newAttributes.put(new BasicAttribute("dbid", Integer.toString(userInfoId)));
            newAttributes.put(new BasicAttribute("uid", newUsername));
            newAttributes.put(new BasicAttribute("realname", (realname == null || realname.isEmpty()) ? newUsername : realname));
            newAttributes.put(new BasicAttribute("displayName", (nickname == null || nickname.isEmpty()) ? newUsername : nickname));
            newAttributes.put(new BasicAttribute("userPassword", PasswordUtils.openLdapMD5(newPassword)));
            newAttributes.put(new BasicAttribute("ou", tenantCode));
            newAttributes.put(new BasicAttribute("status", "1"));
            newAttributes.put(new BasicAttribute("updateTime", cn.com.doone.common.uc.utils.LdapUtils.Timestamp2generalized(new Timestamp(System.currentTimeMillis()), TimeZone.getTimeZone("CST"))));
            
            ldapContext.createSubcontext(distinguishedName, newAttributes);
		} catch (Exception e) {
			throw e;
		} finally {
            LdapUtils.closeContext(ldapContext);
        }
	}
	
	@Override
	public void removeUser(String userAccount, String tenantFullName) throws Exception {
		LdapContext ldapContext = null;
		try {
			ldapContext = ldapContextFactory.getSystemLdapContext();
			
			ModificationItem[] mods = new ModificationItem[2];   
			String updateTime = cn.com.doone.common.uc.utils.LdapUtils.Timestamp2generalized(new Timestamp(System.currentTimeMillis()), TimeZone.getTimeZone("CST"));
			
	        mods[0] = new ModificationItem(LdapContext.REPLACE_ATTRIBUTE, new BasicAttribute("updateTime", updateTime));   
	        mods[1] = new ModificationItem(LdapContext.REPLACE_ATTRIBUTE, new BasicAttribute("status", "0"));   
	        
	        ldapContext.modifyAttributes("CN=" + userAccount + "," + tenantFullName, mods);
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		} finally {
            LdapUtils.closeContext(ldapContext);
        }
		
	}

	@Override
	public String findTenantFullNameByTenantCode(String tenantCode) throws Exception {
		LdapContext ldapContext = null;
		String fullname = "";
		try {
			ldapContext = ldapContextFactory.getSystemLdapContext();
			
			final SearchControls searchCtls = new SearchControls(SearchControls.SUBTREE_SCOPE, 1, 0, null, false, false); 
            final NamingEnumeration<SearchResult> search = ldapContext.search("DC=doone,DC=com,DC=cn", "(&(objectClass=xdwOrganization)(tenantCode=" + tenantCode + "))", searchCtls);
            
            if (search.hasMore()) {
                final SearchResult next = search.next();
                fullname = next.getNameInNamespace();
            } 
		} catch (Exception e) {
			throw e;
		} finally {
            LdapUtils.closeContext(ldapContext);
        }
		
		return fullname;
	}

	@Override
	public void removeNode(String nodename) {
		LdapContext ldapContext = null;
		try {
			ldapContext = ldapContextFactory.getSystemLdapContext();
	        ldapContext.destroySubcontext(nodename);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
            LdapUtils.closeContext(ldapContext);
        }
	}

	@Override
	public void sysnUser(List<Map<String, Object>> userMapList) throws Exception {
		LdapContext ldapContext = null;
		try {
			ldapContext = ldapContextFactory.getSystemLdapContext();
			
			for (Map<String, Object> userMap : userMapList) {
				int userInfoId = (Integer) userMap.get("userInfoId");
				String userAccount = (String) userMap.get("userAccount");
				String password = (String) userMap.get("password");
				String nickname = (String) userMap.get("nickname");
				String realname = (String) userMap.get("realname");
				String email = (String) userMap.get("email");
				String mobilePhone = (String) userMap.get("mobilePhone");
				String status = (String) userMap.get("status");
				
				final SearchControls searchCtls = new SearchControls(SearchControls.SUBTREE_SCOPE, 1, 0, null, false, false); 
	            final NamingEnumeration<SearchResult> search = ldapContext.search("OU=Account,DC=doone,DC=com,DC=cn", "uid=" + userAccount, searchCtls);
	            
	            if (search.hasMore()) {
	            	
	            	ModificationItem[] mods = new ModificationItem[7];   
	    			String updateTime = cn.com.doone.common.uc.utils.LdapUtils.Timestamp2generalized(new Timestamp(System.currentTimeMillis()), TimeZone.getTimeZone("CST"));
	    			
	    	        mods[0] = new ModificationItem(LdapContext.REPLACE_ATTRIBUTE, new BasicAttribute("updateTime", updateTime));   
	    	        mods[1] = new ModificationItem(LdapContext.REPLACE_ATTRIBUTE, new BasicAttribute("status", status));   
	    	        mods[2] = new ModificationItem(LdapContext.REPLACE_ATTRIBUTE, new BasicAttribute("realname", (realname == null || realname.isEmpty()) ? userAccount : realname));   
	    	        mods[3] = new ModificationItem(LdapContext.REPLACE_ATTRIBUTE, new BasicAttribute("displayName", (nickname == null || nickname.isEmpty()) ? userAccount : nickname));   
	    	        mods[4] = new ModificationItem(LdapContext.REPLACE_ATTRIBUTE, new BasicAttribute("mail", email));
	    	        mods[5] = new ModificationItem(LdapContext.REPLACE_ATTRIBUTE, new BasicAttribute("telephoneNumber", (mobilePhone != null && mobilePhone.isEmpty()) ? null : mobilePhone));
	    	       
	    	        if ("0".equals(status)) {
	    	        	mods[6] = new ModificationItem(LdapContext.REPLACE_ATTRIBUTE, new BasicAttribute("userPassword", RandomStringUtils.randomAlphanumeric(16)));
	    	        } else {
	    	        	mods[6] = new ModificationItem(LdapContext.REPLACE_ATTRIBUTE, new BasicAttribute("userPassword", password));
	    	        }
	    	        
	    	        
	    	        ldapContext.modifyAttributes("CN=" + userAccount + ",OU=Account,DC=doone,DC=com,DC=cn", mods);
	            	
	            } else {
	            	String distinguishedName = "CN=" + userAccount + ",OU=Account,DC=doone,DC=com,DC=cn";
	                Attributes newAttributes = new BasicAttributes(true);
	                Attribute oc = new BasicAttribute("objectclass");

	                oc.add("top");   
	                oc.add("account");
	                oc.add("xdwAccount");
	                newAttributes.put(oc);   
	                newAttributes.put(new BasicAttribute("dbid", Integer.toString(userInfoId)));
	                newAttributes.put(new BasicAttribute("uid", userAccount));
	                newAttributes.put(new BasicAttribute("realname", (realname == null || realname.isEmpty()) ? userAccount : realname));
	                newAttributes.put(new BasicAttribute("displayName", (nickname == null || nickname.isEmpty()) ? userAccount : nickname));
	                newAttributes.put(new BasicAttribute("userPassword", password));
	                newAttributes.put(new BasicAttribute("ou", "doone.com.cn"));
	                newAttributes.put(new BasicAttribute("status", "1"));
	                newAttributes.put(new BasicAttribute("updateTime", cn.com.doone.common.uc.utils.LdapUtils.Timestamp2generalized(new Timestamp(System.currentTimeMillis()), TimeZone.getTimeZone("CST"))));
	                
	                ldapContext.createSubcontext(distinguishedName, newAttributes);
	            }
				
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		} finally {
            LdapUtils.closeContext(ldapContext);
        }
		
	}

	@Override
	public void resetPassword(String userAccount, String tenantFullName, String password) {
		LdapContext ldapContext = null;
		try {
			ldapContext = ldapContextFactory.getSystemLdapContext();
			
			ModificationItem[] mods = new ModificationItem[2];   
			String updateTime = cn.com.doone.common.uc.utils.LdapUtils.Timestamp2generalized(new Timestamp(System.currentTimeMillis()), TimeZone.getTimeZone("CST"));
			
	        mods[0] = new ModificationItem(LdapContext.REPLACE_ATTRIBUTE, new BasicAttribute("updateTime", updateTime));   
	        mods[1] = new ModificationItem(LdapContext.REPLACE_ATTRIBUTE, new BasicAttribute("userPassword", PasswordUtils.openLdapMD5(password)));   
	        
	        ldapContext.modifyAttributes("CN=" + userAccount + "," + tenantFullName, mods);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("Exception in add():" + e);
		} finally {
            LdapUtils.closeContext(ldapContext);
        }
	}

}
